package com.zeng.stpro.modules.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zeng.stpro.commons.utils.Constant;
import com.zeng.stpro.commons.utils.JwtUtils;
import com.zeng.stpro.commons.utils.R;
import com.zeng.stpro.commons.utils.ResponseUtils;
import com.zeng.stpro.modules.app.bean.SysUser;
import com.zeng.stpro.modules.security.entity.SecurityUser;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private RedisTemplate redisTemplate;

    public TokenLoginFilter(AuthenticationManager authenticationManager,RedisTemplate redisTemplate) {
        this.authenticationManager = authenticationManager;
        this.redisTemplate = redisTemplate;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/api/admin/login","POST"));
    }

    //1 获取表单提交用户名和密码
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        //获取表单提交数据
        try {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            SysUser user = new SysUser();
            user.setPassword(password);
            user.setUsername(username);
            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword(),new ArrayList<>()));
        //} catch (IOException e) {
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    //2 认证成功调用的方法
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        //认证成功，得到认证成功之后用户信息
        SecurityUser user = (SecurityUser)authResult.getPrincipal();
        //根据用户名生成token
        String token = JwtUtils.createToken(user.getCurrentUserInfo().getUsername());

        //把用户名称 放到redis
        Map<String, Object> userinfo = new HashMap<>();
        userinfo.put(Constant.RedisHashKey.USER.val(), user);
        userinfo.put(Constant.RedisHashKey.TOKEN.val(), token);
        userinfo.put(Constant.RedisHashKey.PROMS.val(), user.getPermissionValueList());
        redisTemplate.opsForHash().putAll(user.getCurrentUserInfo().getUsername(), userinfo);

        //返回token
        ResponseUtils.out(response, R.ok().data(Constant.TOKEN, token));
    }

    //3 认证失败调用的方法
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
            throws IOException, ServletException {


        ResponseUtils.out(response, R.ng());
    }
}
